package com.data.mall.service.impl;

import com.data.mall.common.KafkaTrackingDTO;
import com.data.mall.domain.Promo;
import com.data.mall.etl.domain.enums.Event;
import com.data.mall.etl.domain.enums.Params;
import com.data.mall.kafka.KafkaProduceService;
import com.data.mall.repositry.PromoRepository;
import com.data.mall.service.ItemService;
import com.data.mall.service.PromoService;
import com.data.mall.service.UserService;
import com.data.mall.service.dto.ItemDTO;
import com.data.mall.service.dto.PromoDTO;
import com.data.mall.service.dto.UserDTO;
import com.data.mall.utils.JSON;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author shixukai
 * @Package com.data.mall.service.impl
 * @Description: TODO
 * @date 2021/4/7
 */
@Service
public class PromoServiceImpl implements PromoService {

    @Autowired
    private PromoRepository promoRepository;

    @Autowired
    private ItemService itemService;

    @Autowired
    private UserService userService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    KafkaProduceService kafkaProduceService;

    @Override
    public PromoDTO getPromoByItemId(Long itemId) {
        //获取对应商品的秒杀活动信息
        Promo promo = promoRepository.findByItemId(itemId);

        PromoDTO dto = convertFromDataObject(promo);
        if (dto == null) {
            return null;
        }

        //判断当前秒杀活动即将开始或正在进行
        if (dto.getStartTime().isAfter(LocalDateTime.now())) {
            dto.setStatus(1);
        } else if (dto.getEndTime().isBefore(LocalDateTime.now())) {
            dto.setStatus(3);
        } else {
            dto.setStatus(2);
        }
        return dto;
    }

    @Override
    public void publishPromo(Long promoId) {
        //通过活动获取id
        Optional<Promo> optional = promoRepository.findById(promoId);
        if (optional.isPresent()) {
            Promo promo = optional.get();
            if (promo.getItemId() == null || promo.getItemId().intValue() == 0) {
                return;
            }

            ItemDTO itemDTO = itemService.getItemById(promo.getItemId());
            //将库存同步到redis内
            redisTemplate.opsForValue().set("promo_item_stock_" + itemDTO.getId(), itemDTO.getStock());

            //将大闸的限制数字设到redis内
            redisTemplate.opsForValue().set("promo_door_count_" + promoId, itemDTO.getStock().intValue() * 5);

            // 埋点
            KafkaTrackingDTO kafkaTrackingDTO = KafkaTrackingDTO.builder()
                    .event(Event.PUBLISH_PROMOTION)
                    .param(Params.PROMOTION, JSON.toJSONString(convertFromDataObject(promo)))
                    .build();
            kafkaProduceService.sendTrackingMessage(kafkaTrackingDTO);

        }
    }

    @Override
    public String generateSecondKillToken(Long promoId, Long itemId, Long userId) {
        //判断是否库存已售罄，若对应的售罄key存在，则直接返回下单失败
        if (redisTemplate.hasKey("promo_item_stock_invalid_" + itemId)) {
            return null;
        }

        Promo promo = promoRepository.findById(promoId).orElse(null);

        PromoDTO dto = convertFromDataObject(promo);
        if (dto == null) {
            return null;
        }

        //判断当前时间是否秒杀活动即将开始或正在进行
        if (dto.getStartTime().isAfter(LocalDateTime.now())) {
            dto.setStatus(1);
        } else if (dto.getEndTime().isBefore(LocalDateTime.now())) {
            dto.setStatus(3);
        } else {
            dto.setStatus(2);
        }
        //判断活动是否正在进行
        if (dto.getStatus().intValue() != 2) {
            return null;
        }
        //判断item信息是否存在
        ItemDTO itemModel = itemService.getItemByIdInCache(itemId);
        if (itemModel == null) {
            return null;
        }
        //判断用户信息是否存在
        UserDTO userModel = userService.getUserByIdInCache(userId);
        if (userModel == null) {
            return null;
        }

        //获取秒杀大闸的count数量
        long result = redisTemplate.opsForValue().increment("promo_door_count_" + promoId, -1);
        if (result < 0) {
            return null;
        }
        //生成token并且存入redis内并给一个5分钟的有效期
        String token = UUID.randomUUID().toString().replace("-", "");

        redisTemplate.opsForValue().set("promo_token_" + promoId + "_userid_" + userId + "_itemid_" + itemId, token);
        redisTemplate.expire("promo_token_" + promoId + "_userid_" + userId + "_itemid_" + itemId, 5, TimeUnit.MINUTES);

        return token;
    }


    private PromoDTO convertFromDataObject(Promo promo) {
        if (promo == null) {
            return null;
        }
        PromoDTO dto = PromoDTO.builder().build();
        BeanUtils.copyProperties(promo, dto);
        return dto;
    }
}
